package com.fitso.model.calculator.bmi;

import java.math.BigDecimal;
import java.math.MathContext;

import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import com.fitso.model.bean.Body;
import com.fitso.model.bean.measure.length.Length;
import com.fitso.model.bean.measure.length.Meter;
import com.fitso.model.bean.measure.mass.KiloGram;
import com.fitso.model.bean.measure.mass.Mass;
import com.fitso.model.calculator.BodyMassIndexCalculator;

/**
 * <p>
 * Ratio of body mass over height. This should not be used to determine obesity
 * as a body builder could easily have a high BMI since their mass to height
 * ratio is very high.
 * </p>
 * <p>
 * <code>
 * SI - weight (kg)/height<sup>2</sup> (m<sup>2</sup>)<br />
 * Emperial - weight (lb) x 703/ height<sup>2</sup> (in<sup>2</sup>)
 * </code>
 * </p>
 * 
 * @author timothystorm
 */
@Component("StandardBodyMassIndexCalculator")
public class StandardBodyMassIndexCalculator implements BodyMassIndexCalculator {

	public Double calculate(Body body) {
		Assert.notNull(body, "body required");

		return calculate(body.getHeight(), body.getWeight());
	}

	public Double calculate(Length height, Mass weight) {
		BigDecimal mass = new KiloGram(weight).getValue();
		BigDecimal length = new Meter(height).getValue();

		Assert.isTrue(length.doubleValue() > 0, "length must be positive non negative");
		return mass.divide(length.pow(2), MathContext.DECIMAL32).doubleValue();
	}
}
